﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Brain.Logic2D.PathFinding.Tiled
{
    public class Map
    {
        public Node[,] Nodes { get; protected set; }

        public int Width;
        public int Height;

        public Map(ushort width, ushort height)
        {
            this.Width = width;
            this.Height = height;
            Nodes = new Node[width, height];
        }

        public int BlockSize;

        /// <summary>
        /// Creates the Map from a Texture. Only PURE black(R:0 G:0 B:0) will be blocked,
        /// any other color are passable.
        /// </summary>
        /// <param name="textureName"></param>
        /// <param name="blockSize"></param>
        public Map(string texturePlace, ushort blockSize)
        {
            Texture2D texture = Engine.Instance.ContentManager.Load<Texture2D>(texturePlace);

            BlockSize = blockSize;
            if (texture.Width % blockSize != 0 ||
                texture.Height % blockSize != 0)
            {
                throw new Exception("The Texture Width/Height can't be divided by the block Size you provided");
            }

            this.Width = texture.Width / blockSize;
            this.Height = texture.Height / blockSize;
            Nodes = new Node[Width, Height];

            Color[] colors = new Color[texture.Width * texture.Height];
            texture.GetData<Color>(colors);

            for (ushort x = 0; x < Width; x++)
            {
                int realX = x * blockSize;
                for (ushort y = 0; y < Height; y++)
                {
                    int realY = y * blockSize;

                    Color color = colors[(realY * texture.Width) + realX];
                    Node node = new Node();
                    if (color.R == 0 &&
                        color.G == 0 &&
                        color.B == 0)
                    {
                        node.Blocked = true;
                    }
                    else
                    {
                        node.Blocked = false;
                    }
                    node.X = x;
                    node.Y = y;
                    node.Rectangle = new Rectangle(x * blockSize, y * blockSize, blockSize, blockSize);
                    SubmitNode(node, x, y);
                }
            }

            FinishedMaking();
        }

        public virtual void SubmitNode(Node node, ushort x, ushort y)
        {
            Nodes[x, y] = node;
            node.X = x;
            node.Y = y;
        }

        public virtual Node GetNode(Vector2 position)
        {
            int x = (int)(position.X / BlockSize);
            int y = (int)(position.Y / BlockSize);
            return Nodes[x, y];
        }

        /// <summary>
        /// Will optimize the Map. Only call it if you made the map without using
        /// a Texture, with the default (width, height) constructor. Else, DON'T FORGET TO CALL IT, 
        /// or the PathFinder can get slower or even not work
        /// </summary>
        public virtual void FinishedMaking()
        {
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    Node node = Nodes[x, y];

                    // Left
                    if (x > 0)
                    {
                        int left = x - 1;
                        Node leftN = Nodes[left, y];
                        node.LeftNode = leftN;
                    }
                    // Right
                    if (x < Width - 1)
                    {
                        int right = x + 1;
                        Node rightN = Nodes[right, y];
                        node.RightNode = rightN;
                    }
                    // Up
                    if (y < Height - 1)
                    {
                        int up = y + 1;
                        Node upN = Nodes[x, up];
                        node.UpNode = upN;
                    }
                    // Down
                    if (y > 0)
                    {
                        int down = y - 1;
                        Node downN = Nodes[x, down];
                        node.DownNode = downN;
                    }
                }
            }
        }
    }
}
